package com.xique.park.command.controller;

import cn.hutool.core.util.StrUtil;
import com.xique.common.core.utils.SecurityUtils;
import com.xique.common.core.utils.SpringUtils;
import com.xique.common.core.utils.command.CommandResultUtil;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.common.log.annotation.Log;
import com.xique.common.log.enums.BusinessType;
import com.xique.common.security.annotation.PreAuthorize;
import com.xique.park.command.config.CommandContext;
import com.xique.park.command.handler.MarkCarInoutCommandHandler;
import com.xique.park.command.handler.base.BaseCommand;
import com.xique.park.constant.CommandConstant;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * 设备命令下发 controller
 *
 * @author WLD
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/command")
public class CommandController {

    private final CommandContext commandContext;

    /**
     * 通用命令下发
     * <p>
     * 适用：
     * 【设置时间】、【获取时间】、【重启设备】、【重启应用程序】、【重启设备监控进程】、【下载车辆信息】
     * 【获取车辆信息】、【获取车辆数量】、【删除全部车辆】、【下载车辆管理类型】、【获取车辆管理类型】
     * 【删除车辆管理类型】、【删除全部车辆管理类型】、【下载车辆管理类型通道通行权限】
     * 【获取车辆管理类型通道通行权限】、【删除车辆管理类型通道通行权限】、【删除全部车辆管理类型通道通行权限】
     * 【设置设备参数】、【设置通道参数】、【设置车场参数】、【获取车场参数】、【获取通道参数】
     * 【设置LED屏参数】、【获取LED屏参数】、【设置车辆管理类型的计费价格】、【获取车辆管理类型的计费价格】
     * 【删除全部管理类型的计费价格】、【下载计费价格】、【删除全部计费价格】、【设备初始化】、【下载文件】、【获取文件】、
     * 【固件升级】、【设备上线通知】、【设备离线通知】
     *
     * @param laneId     通道ID：[设置设备参数、设置通道参数]需要
     * @param cmd        命令
     * @param sn         设备号
     * @param mngTypeIds 管理类型ID，多个以 , 分隔：[设置车辆管理类型的计费价格]需要
     * @param file       文件：[下载文件]需要
     * @param fileName   文件名：[固件升级]需要
     */
    @Log(title = "通用命令下发", businessType = BusinessType.COMMAND)
    @PostMapping("/commonIssue")
    public AjaxResult commonIssue(Long laneId, String cmd, String sn, String mngTypeIds, MultipartFile file, String fileName) {
        if (cmd == null || StrUtil.isBlank(sn)) {
            log.warn("[设备命令下发]参数错误，cmd：{}，sn：{}", cmd, sn);
            return AjaxResult.error("参数错误");
        }
        // 获取命令对应的执行类
        BaseCommand baseCommand = (BaseCommand) SpringUtils.getBean(commandContext.getCommand(cmd));
        AjaxResult commandResult = baseCommand.issue(SecurityUtils.getParkId(), laneId, mngTypeIds, sn, file, fileName, cmd);
        return CommandResultUtil.handleCommandResult(commandResult, "");
    }

    /**
     * 手动入场或出场
     *
     * @param sn           设备编号
     * @param cmd          命令
     * @param plate        车牌
     * @param carType      车辆类型
     * @param inOrOutTime  入场或出场时间
     * @param remark       备注
     * @param isNoOpenGate 0：开闸，1：不开闸
     */
    @PreAuthorize(hasAnyPermi = {"park:ipc:handIn","park:ipc:handOut"})
    @Log(title = "手动入场 | 出场", businessType = BusinessType.COMMAND)
    @PostMapping("/markCarInOrOut")
    public AjaxResult markCarInOrOut(String sn, String cmd, String plate, Integer carType, String inOrOutTime, String remark, Integer isNoOpenGate) {
        if (StrUtil.isBlank(plate) || StrUtil.isBlank(sn) || null == carType || null == inOrOutTime) {
            log.warn("[设备命令下发]手动入场或出场参数错误，sn：{}，plate：{}，inOrOutTime：{}，carType：{}，isNoOpenGate，：{}，remark：{}",
                    sn, plate, inOrOutTime, carType, isNoOpenGate, remark);
            return AjaxResult.error("参数错误");
        }
        if (StrUtil.isBlank(cmd)) {
            cmd = CommandConstant.MARK_CAR_IN_OR_OUT_CMD;
        }
        MarkCarInoutCommandHandler markCarInoutCommandHandler = (MarkCarInoutCommandHandler) SpringUtils.getBean(commandContext.getCommand(cmd));
        markCarInoutCommandHandler.setPlate(plate);
        markCarInoutCommandHandler.setInOrOutTime(inOrOutTime);
        markCarInoutCommandHandler.setCarType(carType);
        markCarInoutCommandHandler.setIsNoOpenGate(isNoOpenGate);
        AjaxResult commandResult = markCarInoutCommandHandler.issue(SecurityUtils.getParkId(), sn, cmd);
        return CommandResultUtil.handleCommandResult(commandResult, "");
    }

    /**
     * 远程开闸
     */
    @Log(title = "远程开闸", businessType = BusinessType.COMMAND)
    @PostMapping("/openGate")
    public AjaxResult openGate(String sn) {
        if (StrUtil.isBlank(sn)) {
            log.warn("[设备命令下发]远程开闸参数错误，sn：{}", sn);
            return AjaxResult.error("参数错误");
        }
        BaseCommand baseCommand = (BaseCommand) SpringUtils.getBean(commandContext.getCommand(CommandConstant.SET_GATE_CMD));
        AjaxResult commandResult = baseCommand.issue(SecurityUtils.getParkId(), sn, CommandConstant.SET_OR_CLOSE_GATE_CMD);
        return CommandResultUtil.handleCommandResult(commandResult, "");
    }

    /**
     * 远程关闸
     */
    @Log(title = "远程关闸", businessType = BusinessType.COMMAND)
    @PostMapping("/closeGate")
    public AjaxResult closeGate(String sn) {
        if (StrUtil.isBlank(sn)) {
            log.warn("[设备命令下发]远程关闸参数错误，sn：{}", sn);
            return AjaxResult.error("参数错误");
        }
        BaseCommand baseCommand = (BaseCommand) SpringUtils.getBean(commandContext.getCommand(CommandConstant.CLOSE_GATE_CMD));
        AjaxResult commandResult = baseCommand.issue(SecurityUtils.getParkId(), sn, CommandConstant.SET_OR_CLOSE_GATE_CMD);
        return CommandResultUtil.handleCommandResult(commandResult, "");
    }

}
